package services

import (
	"errors"
	"fmt"
	"rego-top/config"
	"rego-top/database"
	"rego-top/dto"
	"rego-top/models"
	"rego-top/utils"
	"time"

	"gopkg.in/gomail.v2"
	"gorm.io/gorm"
)

type EmailService struct{}

func NewEmailService() *EmailService {
	return &EmailService{}
}

// SendVerificationEmail 发送邮箱验证邮件
func (s *EmailService) SendVerificationEmail(email, token string) error {
	cfg := config.AppConfig.Email
	
	m := gomail.NewMessage()
	m.SetHeader("From", cfg.FromEmail)
	m.SetHeader("To", email)
	m.SetHeader("Subject", "邮箱验证 - Rego Top")
	
	verificationURL := fmt.Sprintf("http://localhost:%s/api/auth/verify-email?token=%s", 
		config.AppConfig.Server.Port, token)
	
	body := fmt.Sprintf(`
		<h2>邮箱验证</h2>
		<p>感谢您注册 Rego Top！</p>
		<p>请点击下面的链接验证您的邮箱地址：</p>
		<p><a href="%s">验证邮箱</a></p>
		<p>如果您无法点击链接，请复制以下地址到浏览器中打开：</p>
		<p>%s</p>
		<p>此链接将在24小时后过期。</p>
		<p>如果您没有注册账户，请忽略此邮件。</p>
	`, verificationURL, verificationURL)
	
	m.SetBody("text/html", body)
	
	d := gomail.NewDialer(cfg.SMTPHost, cfg.SMTPPort, cfg.SMTPUser, cfg.SMTPPassword)
	
	return d.DialAndSend(m)
}

// SendPasswordResetEmail 发送密码重置邮件
func (s *EmailService) SendPasswordResetEmail(email, token string) error {
	cfg := config.AppConfig.Email
	
	m := gomail.NewMessage()
	m.SetHeader("From", cfg.FromEmail)
	m.SetHeader("To", email)
	m.SetHeader("Subject", "密码重置 - Rego Top")
	
	resetURL := fmt.Sprintf("http://localhost:%s/api/auth/reset-password?token=%s", 
		config.AppConfig.Server.Port, token)
	
	body := fmt.Sprintf(`
		<h2>密码重置</h2>
		<p>您好！</p>
		<p>我们收到了您的密码重置请求。</p>
		<p>请点击下面的链接重置您的密码：</p>
		<p><a href="%s">重置密码</a></p>
		<p>如果您无法点击链接，请复制以下地址到浏览器中打开：</p>
		<p>%s</p>
		<p>此链接将在1小时后过期。</p>
		<p>如果您没有请求重置密码，请忽略此邮件。</p>
	`, resetURL, resetURL)
	
	m.SetBody("text/html", body)
	
	d := gomail.NewDialer(cfg.SMTPHost, cfg.SMTPPort, cfg.SMTPUser, cfg.SMTPPassword)
	
	return d.DialAndSend(m)
}

// ForgotPassword 忘记密码
func (s *EmailService) ForgotPassword(req dto.ForgotPasswordRequest) error {
	var user models.User
	if err := database.DB.Where("email = ?", req.Email).First(&user).Error; err != nil {
		if err == gorm.ErrRecordNotFound {
			// 为了安全，即使邮箱不存在也返回成功
			return nil
		}
		return errors.New("查询用户失败")
	}

	// 生成重置令牌
	resetToken, err := utils.GenerateRandomString(32)
	if err != nil {
		return errors.New("生成重置令牌失败")
	}

	// 更新用户的重置令牌
	user.PasswordResetToken = resetToken
	expiry := time.Now().Add(1 * time.Hour) // 1小时后过期
	user.PasswordResetExpiry = &expiry

	if err := database.DB.Save(&user).Error; err != nil {
		return errors.New("保存重置令牌失败")
	}

	// 发送重置邮件
	return s.SendPasswordResetEmail(user.Email, resetToken)
}

// ResetPassword 重置密码
func (s *EmailService) ResetPassword(req dto.ResetPasswordRequest) error {
	var user models.User
	if err := database.DB.Where("password_reset_token = ?", req.Token).First(&user).Error; err != nil {
		return errors.New("无效的重置令牌")
	}

	// 检查令牌是否过期
	if user.PasswordResetExpiry != nil && time.Now().After(*user.PasswordResetExpiry) {
		return errors.New("重置令牌已过期")
	}

	// 加密新密码
	hashedPassword, err := utils.HashPassword(req.Password)
	if err != nil {
		return errors.New("密码加密失败")
	}

	// 更新密码并清除重置令牌
	user.Password = hashedPassword
	user.PasswordResetToken = ""
	user.PasswordResetExpiry = nil

	return database.DB.Save(&user).Error
}

// ResendVerificationEmail 重新发送验证邮件
func (s *EmailService) ResendVerificationEmail(email string) error {
	var user models.User
	if err := database.DB.Where("email = ?", email).First(&user).Error; err != nil {
		return errors.New("用户不存在")
	}

	if user.IsEmailVerified {
		return errors.New("邮箱已经验证过了")
	}

	// 生成新的验证令牌
	emailToken, err := utils.GenerateRandomString(32)
	if err != nil {
		return errors.New("生成验证令牌失败")
	}

	// 更新验证令牌
	user.EmailVerificationToken = emailToken
	expiry := time.Now().Add(24 * time.Hour)
	user.EmailVerificationExpiry = &expiry

	if err := database.DB.Save(&user).Error; err != nil {
		return errors.New("保存验证令牌失败")
	}

	// 发送验证邮件
	return s.SendVerificationEmail(user.Email, emailToken)
}